//using System;
//using System.Runtime.InteropServices;
//using System.IO;
//
//#if OPENGL
//#if MONOMAC
//using MonoMac.OpenGL;
//#elif WINDOWS || LINUX
//using OpenTK.Graphics.OpenGL;
//#elif GLES
//using System.Text;
//using OpenTK.Graphics.ES20;
//using ShaderType = OpenTK.Graphics.ES20.All;
//using ShaderParameter = OpenTK.Graphics.ES20.All;
//using TextureUnit = OpenTK.Graphics.ES20.All;
//using TextureTarget = OpenTK.Graphics.ES20.All;
//#endif
//#elif DIRECTX
//using SharpDX;
//using SharpDX.Direct3D;
//using SharpDX.Direct3D11;
//using SharpDX.DXGI;
//#elif PSM
//enum ShaderType //FIXME: Major Hack
//{
//	VertexShader,
//	FragmentShader
//}
//#endif

#ifndef Shader_h
#define Shader_h

#include <Defines.h>
#include <CSharpPropertyMethods.h>

// Riccsson includes.
#include <System/Object.h>
#include <System/IntPtr.h>
#include <System/Type.h>
#include <System/String.h>
#include <System/IO/BinaryReader.h>

// XNA includes.
#include "../../DisplayOrientation.h"
#include "../../Rectangle.h"
#include "../States/DepthFormat.h"
#include "../SurfaceFormat.h"
#include "../RenderTargetUsage.h"
#include "../States/SamplerState.h"
#include "ShaderStage.h"

namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			namespace Graphics
			{
				/*internal*/ enum class SamplerType
				{
					Sampler2D = 0,
					SamplerCube = 1,
					SamplerVolume = 2,
					Sampler1D = 3,
				};

				// TODO: We should convert the sampler info below 
				// into the start of a Shader reflection API.

				/*internal*/ struct SamplerInfo
				{
					public: SamplerType type;
					public: int textureSlot;
					public: int samplerSlot;
					public: GC_PTR<Riccsson::System::string> name;
					public: GC_PTR<SamplerState> state;

					// TODO: This should be moved to EffectPass.
					public: int parameter;

					public: SamplerInfo()
					{
						throw;
					}
					public: SamplerInfo(const SamplerInfo& other)
					{
						throw;
					}
				};

				/*internal*/ class Shader
					: public GraphicsResource
				{
			#if OPENGL

					// The shader handle.
					private: int _shaderHandle = -1;

					// We keep this around for recompiling on context lost and debugging.
					private: readonly string _glslCode;

					private: struct Attribute
					{
						public: VertexElementUsage usage;
						public: int index;
						public: string name;
						public: short format;
						public: int location;
					}

					private: Attribute[] _attributes;

			#elif DIRECTX

					public: /*internal*/ VertexShader _vertexShader;

					public: /*internal*/ PixelShader _pixelShader;

					public: byte[] Bytecode { get; private: set; }

			#endif

					/// <summary>
					/// A hash value which can be used to compare shaders.
					/// </summary>
					public: /*internal*/ int HashKey; // { get; private: set; }

					public: GC_PTR<Riccsson::System::Array<SamplerInfo>> Samplers; // { get; private: set; }

					public: GC_PTR<Riccsson::System::Array<int>> CBuffers; // { get; private: set; }

					public: ShaderStage Stage; // { get; private: set; }
		
					public: /*internal*/ Shader(GraphicsDevice* device, Riccsson::System::IO::BinaryReader* reader)
					{

					}

					/*internal*/ protected: override void GraphicsDeviceResetting()
					{
			#if OPENGL
						if (_shaderHandle != -1)
						{
							if (GL.IsShader(_shaderHandle))
							{
								GL.DeleteShader(_shaderHandle);
								GraphicsExtensions.CheckGLError();
							}
							_shaderHandle = -1;
						}
			#endif
					}

					protected: override void Dispose(bool disposing)
					{

						GraphicsResource::Dispose(disposing);
					}
				};


				//bool operator ==(const SamplerInfo& left, const SamplerInfo& right);
				//bool operator !=(const SamplerInfo& left, const SamplerInfo& right);
				inline bool operator ==(const SamplerInfo& left, const SamplerInfo& right)
				{
					throw;
				}
				
				inline bool operator !=(const SamplerInfo& left, const SamplerInfo& right)
				{
					throw;
				}
			}
		}
	}
}

#endif
